package com.charles.seckillPlatform.service.impl;

import com.charles.seckillComponentCommon.constants.CacheConstants;
import com.charles.seckillComponentCommon.exceptions.ServiceException;
import com.charles.seckillComponentCommon.utils.BcryptUtil;
import com.charles.seckillComponentCommon.utils.StringUtils;
import com.charles.seckillComponentSecurity.utils.ThreadUtil;
import com.charles.seckillPlatform.mapper.SysBankMapper;
import com.charles.seckillPlatform.service.BankCheckService;
import com.charles.seckillPlatform.vo.BankCardInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class BankCheckServiceImpl implements BankCheckService {

    public final static String UN_VALID_STATUS = "1";

    public final static int MAX_ATTEMPTS = 5;

    @Autowired
    private SysBankMapper sysBankMapper;
    
    @Autowired
    @Qualifier("myRedisTemplate")
    private RedisTemplate redisTemplate;
    
    @Override
    public BankCardInfo validBankInfo(String payPassword, String orderId) {
        if (StringUtils.isEmpty(payPassword)) {
            throw new ServiceException("请输入支付密码");
        }
        
        Long userId = Long.parseLong(ThreadUtil.getUserId());
        BankCardInfo bankCardInfo = sysBankMapper.queryBankCardInfo(userId);

        checkCardStatus(bankCardInfo);

        validPassword(bankCardInfo, payPassword);
        
        return bankCardInfo;
    }

    public void validPassword(BankCardInfo bankCardInfo, String payPassword) {
        String payPasswordWrongKey = CacheConstants.PAY_PASSWORD_WRONG_ID + bankCardInfo.getBankId();
        if (!BcryptUtil.verifyPassword(payPassword, bankCardInfo.getPayPassword())) {
            Integer count = (Integer) redisTemplate.opsForValue().get(payPasswordWrongKey);

            if (count == null) {
                redisTemplate.opsForValue().setIfAbsent(payPasswordWrongKey, 1);
                throw new ServiceException(String.format("您的支付密码输入有误，您还有%d次尝试机会。连续错误达到限制次数后，银行卡将会被锁定以保障安全。", MAX_ATTEMPTS - 1));
            } else if (count >= MAX_ATTEMPTS - 1) {
                sysBankMapper.lockBankCardByBankId(bankCardInfo.getBankId());
                redisTemplate.delete(payPasswordWrongKey);
                throw new ServiceException("您的支付密码输入错误次数过多，银行卡已被锁定，请前往银行解锁。");
            } else {
                redisTemplate.opsForValue().increment(payPasswordWrongKey);
                throw new ServiceException(String.format("您的支付密码输入有误，您还有%d次尝试机会。连续错误达到限制次数后，银行卡将会被锁定以保障安全。", MAX_ATTEMPTS - count - 1));
            }
        }
        // 验证通过后删除
        redisTemplate.delete(payPasswordWrongKey);
    }

    public void checkCardStatus(BankCardInfo bankCardInfo) {
        if (bankCardInfo.getIsLocked().equals(UN_VALID_STATUS)) {
            throw new ServiceException("您的银行卡当前处于锁定状态，请携带相关证件前往银行营业网点进行解锁操作。");
        }

        if (bankCardInfo.getStatus().equals(UN_VALID_STATUS)) {
            throw new ServiceException("您的银行卡已办理挂失手续，请前往银行网点进行线下处理。");
        }
    }
}
